/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "Proportional.h"
#include <xml/Stream.h>
#include <Gluck.h>
#include "resource/Resource.h"
#include "FontVisitor.h"

namespace liba
{
namespace font
{

Proportional::Letter::Letter()
:	symbol( 0 ),
	x( 0 ),
	y( 0 ),
	width( 0 ),
	height( 0 ),
	base_skip( 0 ),
	base_width( 0 )
{}
	
Proportional::Letter::Letter(const Letter & other)
:	symbol( other.symbol ),
	x( other.x ),
	y( other.y ),
	width( other.width ),
	height( other.height ),
	base_skip( other.base_skip ),
	base_width( other.base_width )
{
}

bool Proportional::Letter::on_attribute( xml::Provider * prov, const std::wstring & name, const std::wstring & value )
{
	if( name == L"Code" )
	{
		int code = 0;
		bool result = converter::convert(value, &code);
		symbol = code;
		return result;
	}
	if( name == L"Symbol" )
	{
		if(value.size() != 1)
			return false;

		symbol = value[0];
		return true;
	}
	if( name == L"X" )
		return converter::convert(value, &x);
	if( name == L"Y" )
		return converter::convert(value, &y);
	if( name == L"Width" )
		return converter::convert(value, &width);
	if( name == L"Height" )
		return converter::convert(value, &height);
	if( name == L"BaseSkip" )
		return converter::convert(value, &base_skip);
	if( name == L"BaseWidth" )
		return converter::convert(value, &base_width);
	return false;
}

Proportional::Proportional(resource::Resource* resource, const filesystem::String & name)
:	height( 1 ),
	width( 1 ),
	base( 0 ),
	line_shift( 1 )
{
	if( !xml::StreamResource( resource ).load( &xml::Root(this, "Font") ) )
		THROW(GluckBadResource( __FUNCTION__, "load() failed", name));
}
	
Proportional::Proportional(const Proportional & other) : not_found_letter(other.not_found_letter), height(other.height), 
														 width(other.width), base(other.base), line_shift(other.line_shift)
{
	std::map<wchar_t, Letter>::const_iterator itr = other.letters.begin();
	while(itr != other.letters.end())
	{
		// clone
		letters[itr->first] = Letter(itr->second);
		
		// next
		itr++;
	}
}

Proportional::~Proportional()
{}

const Proportional::Letter & Proportional::get_letter(wchar_t symbol)const
{
	std::map<wchar_t, Letter>::const_iterator it = letters.find( symbol );
	if( it != letters.end() )
		return it->second;
	it = letters.find( 0 );
	if( it != letters.end() )
		return it->second;
	return not_found_letter;
}

bool Proportional::on_attribute( xml::Provider * prov, const std::wstring & name, const std::wstring & value )
{
	if( name == L"Base" )
		return converter::convert(value, &base);
	if( name == L"Size" )
		return converter::convert(value, &line_shift);
	if( name == L"Width" )
		return converter::convert(value, &width);
	if( name == L"Height" )
		return converter::convert(value, &height);
	return false;
}

bool Proportional::on_node( xml::Provider * prov, const std::wstring & name )
{
	if( name == L"Letter" )
	{
		Letter letter;
		if( !prov->parse_object( &letter ) )
			return false;
		if( !letter.height )
			letter.height = height;
		if( !letter.base_width )
			letter.base_width = letter.width;
//		letter.x = (letter.x + 0.5)/width;
//		letter.y = (letter.y + 0.5)/height;
//		letter.width = (letter.width - 1)/width;
//		letter.height = (letter.height - 1)/height;
//		letter.base_skip /= width;
//		letter.base_width /= width;

		letters[ letter.symbol ] = letter;
		return true;
	}
	return false;
}

void Proportional::Accept(FontVisitor* visitor)
{
	visitor->Visit(this);
}

} //namespace liba
} //namespace font

